#region legal messages please read
/*
 * 
 * iFinity Software Development - http://www.ifinity.com.au
 * Copyright (c) 2006 - 2009
 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
 * documentation files (the "Software"), the rights to use, copy, modify, merge, publish, distribute, sublicense
 * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 
 * following conditions:

 * 1. The above copyright notice and this permission notice shall be included in all copies or substantial portions 
 *    of the Software.  
 * 2. The software may not be claimed as the original work and may not be sold as a stand alone product

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 * 
 */
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

using DotNetNuke.Entities.Portals;
using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Definitions;
using DotNetNuke.Services.Localization;

/* forum specific references */
//using DotNetNuke.Modules.Forum;

using DotNetNuke.Providers.SearchEngineSiteMapProvider;
using DotNetNuke.Providers.ForumSiteMapProvider.Entities;
using DotNetNuke.Providers.ForumSiteMapProvider.Data;
namespace DotNetNuke.Providers.ForumSiteMapProvider
{
    public class ForumSiteMapProvider : SiteMapProvider
    {
        private int _maxEntries = -1;
        private Dictionary<int, LastPositionInfo> _lastSitemapPositions = new Dictionary<int, LastPositionInfo>();
        public ForumSiteMapProvider (string name, System.Collections.Specialized.NameValueCollection config) : base (name, config)
        {
            base.Initialize(name, config);
            _maxEntries = GetSafeSetting(config, "maxEntries", -1);
        }
        public override List<SitePage> SitePagesForTab(DotNetNuke.Entities.Portals.PortalAliasInfo portalAlias, DotNetNuke.Entities.Tabs.TabInfo tab, DotNetNuke.Services.Localization.Locale locale, int sitemapNum, int urlCount, int startingCount, int endingCount)
        {
            List<SitePage> forumUrls = new List<SitePage>();
            //find the forum module(s) on the tab
            base.SetBaseURL(portalAlias.HTTPAlias); //get the base url and portal alias url
            //get the tab, portal and blog information
            if (portalAlias == null)
                throw new Exception("No PortalInfo found for URL (" + _portalAliasURL + ")");

            ModuleController modCtl = new ModuleController();
            ModuleDefinitionController modDefs = new ModuleDefinitionController();

            tab.Modules = modCtl.GetPortalTabModules(portalAlias.PortalID, tab.TabID);
            if (tab.Modules != null)
            {
                foreach (ModuleInfo mod in tab.Modules)
                {
                    //check each modeul on the page, looking for the blog-specific ones
                    List<SitePage> modulePages = new List<SitePage>();
                    ModuleDefinitionInfo modDef = modDefs.GetModuleDefinition(mod.ModuleDefID);
                    string modDefFriendlyName = modDef.FriendlyName;
                    switch (modDefFriendlyName.ToLower())
                    {
                        case "forum":
                            //get entries for forum
                            List<SitePage> forumEntries = GetForumEntries();
                            
                            forumEntries = GetForumEntries(mod, tab, locale, sitemapNum, urlCount, startingCount, endingCount);
                            forumUrls.AddRange(forumEntries);
                            break;
                    }
                }
            }
            return forumUrls;
        }
        #region private methods
        private List<SitePage> GetForumEntries()
        {
            return null;
        }
        private List<SitePage> GetForumEntries(ModuleInfo mod, TabInfo tab, Locale locale, int sitemapNum, int urlCount, int startingCount, int endingCount)
        {
            List<SitePage> pages = new List<SitePage>();
            ChangeFrequencies defaultChangeFreq = SitePage.ConvertChangeFrequencyToEnum(_defaultPageUpdateFrequency);
            List<ThreadInfo> threads;
            List<GroupInfo> groups;
            List<ForumInfo> forums;
            int fromGroupId, fromForumId, fromThreadId, maxCount, totalResults, rowsRemaining;
            if (sitemapNum > 1) //not the first sitemap
            {
                int lastSitemapNum = sitemapNum - 1;
                if (_lastSitemapPositions.ContainsKey(lastSitemapNum))
                {
                    LastPositionInfo lastPosition = _lastSitemapPositions[lastSitemapNum];
                    fromGroupId = lastPosition.LastGroupId;
                    fromThreadId = lastPosition.LastThreadId;
                    fromForumId = lastPosition.LastForumId;
                }
                else
                {
                    fromGroupId = 0;
                    fromForumId = 0;
                    fromThreadId = 0;
                }
            }
            else
            {
                fromGroupId = 0;
                fromForumId = 0;
                fromThreadId = 0;
            }
            maxCount = endingCount - startingCount;
            if (maxCount > _maxEntries && _maxEntries > 0) maxCount = _maxEntries;//restrict count if necessary - the maxEntries is local to the provider
            DataProvider.Instance().GetForumsGroupsAndThreads(mod.PortalID, mod.ModuleID, fromGroupId, fromForumId, fromThreadId, maxCount, out totalResults, out rowsRemaining, out groups, out forums, out threads);
            
            //get the sitemap pages
            //groups first
            LastPositionInfo thisSitemapPosition = new LastPositionInfo();
            int count = 0;
            foreach (GroupInfo group in groups)
            {
                pages.Add(GetSiteMapEntryForGroup(group, tab, locale));
                thisSitemapPosition.LastGroupId = group.GroupId;
                count++;
                if (_maxEntries > 0 && _maxEntries > count) break;
            }
            foreach (ForumInfo forum in forums)
            {
                pages.Add(GetSiteMapEntryForFOrum(forum, tab, locale));
                thisSitemapPosition.LastForumId = forum.ForumId;
                count++;
                if (_maxEntries > 0 && _maxEntries > count) break;

            }
            foreach (ThreadInfo thread in threads)
            {
                pages.Add(GetSiteMapEntryForThread(thread, tab, locale));
                thisSitemapPosition.LastThreadId = thread.ThreadId;
                count++;
                if (_maxEntries > 0 && _maxEntries > count) break;

            }
            if (_lastSitemapPositions.ContainsKey(sitemapNum) == false)
                _lastSitemapPositions.Add(sitemapNum, thisSitemapPosition);
            else
                _lastSitemapPositions[sitemapNum] = thisSitemapPosition;

            return pages;
        }

        private SitePage GetSiteMapEntryForThread(ThreadInfo thread, TabInfo tab, Locale locale)
        {
            SitePage page = new SitePage();
            string language = "";
            if (locale !=null)
                language = locale.Code;
            List<string> parms = new List<string>();
            parms.Add("forumid=" + thread.ForumId.ToString());
            parms.Add("threadid=" + thread.ThreadId.ToString());
            parms.Add("scope=posts");
            string url = GetTabUrl(tab, language, parms.ToArray());
            page.Loc = url;
            DateTime lastMod = thread.PinnedDate;
            if (thread.LatestPostDate > lastMod)
                lastMod = thread.LatestPostDate;
            if (thread.EarliestPostDate > lastMod)
                lastMod = thread.EarliestPostDate;
            page.LastMod = lastMod;
            page.Priority = (double)thread.SitemapPriority;
            TimeSpan timeSinceLastPost = DateTime.Now - thread.LatestPostDate;
            page.ChangeFreq = base.GetChangeFrequencyFromLastChange(timeSinceLastPost);
            return page;
        }

        private SitePage GetSiteMapEntryForFOrum(ForumInfo forum, TabInfo tab, Locale locale)
        {
            SitePage page = new SitePage();
            string language = "";
            if (locale != null)
                language = locale.Code;
            List<string> parms = new List<string>();
            parms.Add("forumid=" + forum.ForumId.ToString());
            parms.Add("scope=threads");
            string url = GetTabUrl(tab, language, parms.ToArray());
            page.Loc = url;
            DateTime lastMod = forum.CreatedDate;
            if (forum.UpdatedDate > lastMod)
                lastMod = forum.UpdatedDate;
            if (forum.LastPostDate > lastMod)
                lastMod = forum.LastPostDate;
            page.LastMod = lastMod ;
            page.Priority = (double)forum.SitemapPriority;
            TimeSpan timeSinceLastPost = DateTime.Now - lastMod;
            page.ChangeFreq = base.GetChangeFrequencyFromLastChange(timeSinceLastPost);
            return page;
            
        }

        private SitePage GetSiteMapEntryForGroup(GroupInfo group, TabInfo tab, Locale locale)
        {
            SitePage page = new SitePage();
            string language = "";
            if (locale != null)
                language = locale.Code;
            List<string> parms = new List<string>();
            parms.Add("groupid=" + group.GroupId.ToString());
            string url = GetTabUrl(tab, language, parms.ToArray());
            page.Loc = url;
            DateTime lastMod = group.CreatedDate;
            page.LastMod = group.UpdatedDate;
            page.Priority = _defaultPagePriority;
            TimeSpan timeSinceLastPost = DateTime.Now - lastMod;
            page.ChangeFreq = base.GetChangeFrequencyFromLastChange(timeSinceLastPost);
            return page;
        }

        
        //private List<SitePage> GetForumEntries(ModuleInfo mod, TabInfo tab, Locale locale, int sitemapNum, int urlCount, int startingCount, int endingCount)
        //{
        //    List<SitePage> pages = new List<SitePage>();
        //    ChangeFrequencies defaultChangeFreq = SitePage.ConvertChangeFrequencyToEnum(_defaultPageUpdateFrequency);
        //    ForumController fc = new ForumController();
        //    ThreadController tc = new ThreadController();
        //    //get all the forums that belong to this module
        //    List<ForumInfo> moduleForums = CBO.FillCollection<ForumInfo>(DotNetNuke.Modules.Forum.DataProvider.Instance().ForumsGetByModuleID(mod.ModuleID));
        //    //5.0 compatible : have removed the publicly accessible methods 
        //    //List<ForumInfo> moduleForums = fc.GetForumByModuleID(mod.ModuleID);
        //    int totalRecords = 0; int maxForumViews = 0; int mostViewedForum = 0;
        //    double priorityStep = 0.0;
        //    //calculate the priority step by comparing max and default
        //    if (_maxPagePriority > _defaultPagePriority)
        //        priorityStep = (_maxPagePriority - _defaultPagePriority) / 4;

        //    Dictionary<int, SitePage> forumPages = new Dictionary<int, SitePage>();//keeps the forum pages
        //    Dictionary<int, SitePage> threadPages = new Dictionary<int, SitePage>();
        //    //Dictionary<int, Dictionary<int, SitePage>> forumThreadPages = new Dictionary<int, Dictionary<int, SitePage>>(); //keeps the thread pages for the forums
        //    bool sitemapThreads = false; //variable tracks whether using the 5.0+ getSitemapThreads call.
        //    bool sitemapThreadsDone = false; 
        //    foreach (ForumInfo forum in moduleForums)
        //    {
        //        DateTime firstForumPostDate = forum.CreatedDate;
        //        DateTime lastForumPostDate = forum.CreatedDate;
        //        DateTime lastPostUpdate = forum.UpdatedDate;
        //        double forumPriority = SitemapPriority(forum, _defaultPagePriority);
        //        //647 : use late bound call to support forums 4.3 and 4.5
        //        //679 : 10 was hardcoded instead of using maxThreadsPerForum value
        //        if (sitemapThreadsDone == false)
        //        {
        //            List<ThreadInfo> threads = GetAllThreads(mod.ModuleID, forum.ForumID, _maxThreadsPerForum, 0, "", tab.PortalID, ref totalRecords, ref sitemapThreads);
        //            if (threads.Count > 0)  //678: check to see if there are any threads in the forum before creating a link
        //            {
        //                AddToThreadPages(sitemapThreads, tab.TabID, forumPriority,  priorityStep, defaultChangeFreq, threads, ref threadPages, ref lastForumPostDate, ref lastPostUpdate);
        //                if (sitemapThreads) sitemapThreadsDone = true;
        //                /*if (threadViews > maxForumViews)
        //                {
        //                    maxForumViews = threadViews;
        //                    mostViewedForum = forum.ForumID;
        //                }*/
        //            }
        //        }
        //        //create the forum page link
        //        //get the forum url (forumid/1/scope/threads)
        //        string forumLink = GetForumLink(tab, forum);
        //        SitePage forumPage = SitePageFromForumUrl(forumLink, lastForumPostDate, defaultChangeFreq, forumPriority);

        //        //add in the forum page
        //        if (EnableSitemap(forum))
        //        {
        //            forumPages.Add(forum.ForumID, forumPage);
        //        }
        //    }
        //    //check the most viewed forum
        //    if (forumPages.ContainsKey(mostViewedForum))
        //    {
        //        forumPages[mostViewedForum].Priority += priorityStep;
        //    }
        //    //convert the dictionary collections to the output list
        //    foreach (int forumId in forumPages.Keys)
        //    {
        //        pages.Add(forumPages[forumId]);
        //    }
        //    //add in the thread pages to the main collection
        //    foreach (int threadId in threadPages.Keys)
        //    {
        //        SitePage threadPage = threadPages[threadId];
        //        pages.Add(threadPage);
        //    }
        //    return pages;
        //}
        //private bool EnableSitemap(ForumInfo forum)
        //{
        //    PropertyInfo enableSitemapProperty = forum.GetType().GetProperty("EnableSitemap");
        //    bool value = true; //default to true unless value found to the contrary
        //    if (enableSitemapProperty != null)
        //    {
        //        value = (bool)enableSitemapProperty.GetValue(forum, null);
        //    }
        //    return value;
        //}
        //private double SitemapPriority(ForumInfo forum, double defaultPriority)
        //{
        //    double priority = defaultPriority;
        //    PropertyInfo sitemapPriorityProperty = forum.GetType().GetProperty("SitemapPriority");
        //    if (sitemapPriorityProperty != null)
        //    {
        //        float val = (float)sitemapPriorityProperty.GetValue(forum, null);
        //        priority = Convert.ToDouble(val);
        //    }
        //    return priority;
        //}
        //private Dictionary<int, SitePage> AddToThreadPages(bool sitemapThreads, int tabId,double forumPriority, double priorityStep,ChangeFrequencies forumChangeFreq,  List<ThreadInfo> threads,ref Dictionary<int, SitePage> threadPages, ref DateTime lastForumPostDate, ref DateTime lastPostUpdate)
        //{
        //    int threadCount = 0; int threadViews = 0;
        //    int maxThreadViews = 0; int mostViewedThreadId = 0;
        //    //create a dictionary of thread pages
             
        //    foreach (ThreadInfo thread in threads)
        //    {
        //        //get the thread Url (forumid/1/threadid/1/scope/posts)
        //        string threadLink = GetThreadLink(tabId, thread.ForumID , thread.ThreadID);
        //        threadCount++; threadViews += thread.Views;
        //        double threadPriority = forumPriority;
        //        //get the latest post updated time for the thread
        //        lastPostUpdate = thread.LastApprovedPost.UpdatedDate;

        //        //increase popularity for each of the markers of popularity
        //        if (thread.IsPinned)
        //            threadPriority += priorityStep;
        //        if (thread.IsPopular)
        //            threadPriority += priorityStep;
        //        if (thread.Rating > 3)
        //            threadPriority += priorityStep;

        //        //check which thread has the most views
        //        if (thread.Views > maxThreadViews)
        //        {
        //            maxThreadViews = thread.Views;
        //            mostViewedThreadId = thread.ThreadID;
        //        }

        //        if (lastForumPostDate < lastPostUpdate)
        //            lastForumPostDate = lastPostUpdate;

        //        //get the change frequency for the thread
        //        TimeSpan firstToLastPost = thread.LastApprovedPost.UpdatedDate - thread.CreatedDate;
        //        ChangeFrequencies threadChangeFreq = forumChangeFreq;
        //        if (thread.TotalPosts > 0)
        //        {
        //            //number of hours between first and last post, divided by number of posts in the thread
        //            double avgHoursBetweenThreadPosts = firstToLastPost.TotalHours / thread.TotalPosts;
        //            threadChangeFreq = SitePage.ConvertChangeFrequencyToEnum(avgHoursBetweenThreadPosts);
        //        }
                
        //        //add the thread sitePage object
        //        threadPages.Add(thread.ThreadID, SitePageFromForumUrl(threadLink, thread.LastApprovedPost.UpdatedDate, forumChangeFreq, threadPriority));

        //        //set the forum change frequency to the lowest thread change frequency
        //        if (threadChangeFreq < forumChangeFreq)
        //            forumChangeFreq = threadChangeFreq;

        //        if (threadCount == _maxThreadsPerForum)
        //            break;
        //        //prevPostUpdate = lastPostUpdate;
        //    }
        //    //check the max viewed thread id and increase the priority for that thread
        //    if (threadPages.ContainsKey(mostViewedThreadId))
        //        threadPages[mostViewedThreadId].Priority += priorityStep;


        //    return threadPages;
        //}
        //private string GetThreadLink(int tabId, int forumId, int threadId)
        //{
        //    string link = "";
        //    //Utils.ContainerViewThreadLink(tab.TabID, forum.ForumID, thread.ThreadID);
        //    Type utilsType = Type.GetType("DotNetNuke.Modules.Forum.Utils, DotNetNuke.Modules.Forum", false, true);
        //    object[] parms = new object[3];
        //    parms[0] = tabId;
        //    parms[1] = forumId;
        //    parms[2] = threadId;
        //    MethodInfo containerViewThreadLinkMethod = null;
        //    if (utilsType != null)
        //    {
        //        //utils object found, load up and use
        //        containerViewThreadLinkMethod = utilsType.GetMethod("ContainerViewThreadLink");
        //        if (containerViewThreadLinkMethod != null)
        //        {
        //            object utilsObj = Activator.CreateInstance(utilsType);
        //            link = (string)containerViewThreadLinkMethod.Invoke(utilsObj, parms);
        //        }
        //    }
        //    else
        //    {
        //        //look for new object 
        //        Type linksType = Type.GetType("DotNetNuke.Modules.Forum.Utilities.Links, DotNetNuke.Modules.Forum", false, true);
        //        if (linksType != null)
        //        {
        //            //ok, got the links object 
        //            containerViewThreadLinkMethod = linksType.GetMethod("ContainerViewThreadLink");
        //            //found the method, then call it
        //            if (containerViewThreadLinkMethod != null)
        //            {
        //                object linksObj = Activator.CreateInstance(linksType);
        //                link = (string)containerViewThreadLinkMethod.Invoke(linksObj, parms);
        //            }
        //        }
        //    }
        //    return link;
        //}

        //private string GetForumLink(TabInfo tab, ForumInfo forum)
        //{
        //    string link = "";
        //    //public static string ContainerViewForumLink(int TabId, int ForumId, bool NoReply);
        //    //Public Shared Function ContainerViewForumLink(ByVal TabId As Integer, ByVal ForumId As Integer, ByVal NoReply As Boolean) As String ; 5.0
        //    Type utilsType = Type.GetType("DotNetNuke.Modules.Forum.Utils, DotNetNuke.Modules.Forum", false, true);
        //    MethodInfo containerViewForumLinkMethod = null;
        //    object[] parms = new object[3];
        //    parms[0] = tab.TabID;
        //    parms[1] = forum.ForumID;
        //    parms[2] = false;
        //    if (utilsType != null)
        //    {
        //        //utils object found, load up and use
        //        containerViewForumLinkMethod = utilsType.GetMethod("ContainerViewForumLink");
        //        object utilsObj = Activator.CreateInstance(utilsType);
        //        if (containerViewForumLinkMethod != null)
        //            link = (string)containerViewForumLinkMethod.Invoke(utilsObj, parms);
        //    }
        //    else
        //    {
        //        //look for new object 
        //        Type linksType = Type.GetType("DotNetNuke.Modules.Forum.Utilities.Links, DotNetNuke.Modules.Forum", false, true);
        //        if (linksType != null)
        //        {
        //            //ok, got the links object 
        //            containerViewForumLinkMethod = linksType.GetMethod("ContainerViewForumLink", BindingFlags.Static | BindingFlags.Public);
        //            //found the method, then call it
        //            if (containerViewForumLinkMethod != null)
        //            {
        //                object linksObj = Activator.CreateInstance(linksType);
        //                link = (string)containerViewForumLinkMethod.Invoke(linksObj, parms);
        //            }
        //        }
        //    }
            
        //    return link;
        //}
        ///// <summary>
        ///// This method exists as a way of handling both the forums 4.3 and 4.5 versions.  It late-binds the call to the ThreadController.ThreadGetAll call.
        ///// created for Task 647
        ///// </summary>
        ///// <param name="ModuleId"></param>
        ///// <param name="ForumId"></param>
        ///// <param name="PageSize"></param>
        ///// <param name="PageIndex"></param>
        ///// <param name="Filter"></param>
        ///// <param name="PortalID"></param>
        ///// <returns></returns>
        //private List<ThreadInfo> GetAllThreads(int ModuleId, int ForumId, int PageSize, int PageIndex, string Filter, int PortalID, ref int totalRecords, ref bool sitemapThreads)
        //{
        //    //we are going to call the Forum module as a late bound call, to support both 4.3 and 4.5 versions, in which the binary compatibility changed
        //    ThreadController tc = new ThreadController();
        //    List<ThreadInfo> threads = new List<ThreadInfo>();
        //    MethodInfo threadGetAll = tc.GetType().GetMethod("ThreadGetAll");
        //    if (threadGetAll != null)
        //    {
        //        //forums 4.3
        //        /*public System.Collections.Generic.List<DotNetNuke.Modules.Forum.ThreadInfo> ThreadGetAll(int ModuleId, int ForumId, int PageSize, int PageIndex, string Filter, int PortalID, ref int TotalRecords)
        //            Member of DotNetNuke.Modules.Forum.ThreadController*/
        //        //forums 4.5 - removed the ref out parameter
        //        /*
        //         public System.Collections.Generic.List<DotNetNuke.Modules.Forum.ThreadInfo> ThreadGetAll(int ModuleId, int ForumId, int PageSize, int PageIndex, string Filter, int PortalID)
        //            Member of DotNetNuke.Modules.Forum.ThreadController
        //         */

        //        ParameterInfo[] callParms = threadGetAll.GetParameters();
        //        int lastParm = callParms.GetUpperBound(0);

        //        object[] parmValues = new object[lastParm + 1];
        //        parmValues[0] = ModuleId;
        //        parmValues[1] = ForumId;
        //        parmValues[2] = PageSize;
        //        parmValues[3] = PageIndex;
        //        parmValues[4] = Filter;
        //        parmValues[5] = PortalID;
        //        if (callParms[lastParm].Name == "TotalRecords")
        //        {
        //            parmValues[6] = totalRecords;
        //        }
        //        threads = (List<ThreadInfo>)threadGetAll.Invoke(tc, parmValues);
        //        sitemapThreads = false;
        //    }
        //    else
        //    {
        //        //forums 5.0 : replaced with following function
        //        //Public Function GetSitemapThreads(ByVal PortalID As Integer) As List(Of ThreadInfo)
        //        MethodInfo threadGetSitemapThreads = tc.GetType().GetMethod("GetSitemapThreads");
        //        if (threadGetSitemapThreads != null)
        //        {
        //            ParameterInfo[] callParms = threadGetSitemapThreads.GetParameters();
        //            int lastParm = callParms.GetUpperBound(0);

        //            object[] parmValues = new object[lastParm + 1];
        //            parmValues[0] = PortalID;
        //            threads = (List<ThreadInfo>)threadGetSitemapThreads.Invoke(tc, parmValues);
        //            sitemapThreads = true;
        //        }
        //    }
        //    return threads;
        //}
        //private SitePage SitePageFromForumUrl(string url, DateTime lastChange, ChangeFrequencies changeFreq, double priority)
        //{
        //    SitePage result = new SitePage(url, lastChange, changeFreq, priority);
        //    return result;
        //}
        //private double ListAverage(List<double> doubleList)
        //{
        //    double total = 0;
        //    foreach (double value in doubleList)
        //    {
        //        total += value;
        //    }
        //    double average = total / doubleList.Count;
        //    return average;
        //}
        #endregion
    }
}
